/**
 * @Author wangyl
 * @E-mail wangyl0629@foxmail.com
 **/
package com.wyl.xue.admin.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wyl.xue.admin.security.UserInfoJwt;
import com.wyl.xue.admin.security.user.SecurityUserInfo;
import com.wyl.xue.admin.system.mybatis.entity.SystemUserRole;
import com.wyl.xue.admin.system.mybatis.entity.SystemUsers;
import com.wyl.xue.admin.system.mybatis.service.SystemDepartmentService;
import com.wyl.xue.admin.system.mybatis.service.SystemRoleMenuService;
import com.wyl.xue.admin.system.mybatis.service.SystemUserRoleService;
import com.wyl.xue.admin.system.mybatis.service.SystemUsersService;
import com.wyl.xue.admin.system.service.Department;
import com.wyl.xue.admin.system.service.User;
import com.wyl.xue.admin.system.vo.UserInfoVo;
import com.wyl.xue.admin.system.vo.UserLoginInfo;
import com.wyl.xue.core.util.UserTools;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.sf.cglib.beans.BeanCopier;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @ClassName: UserImpl
 * @Function: TODO
 * @Date: 2020/11/7 22:36
 * @author wyl
 * @version V1.0
 */
@Service
@Slf4j
@AllArgsConstructor
public class UserImpl implements User {
    final BeanCopier copier = BeanCopier.create(UserInfoVo.class, SystemUsers.class, false);
    final BeanCopier copierFrom = BeanCopier.create(SystemUsers.class, UserInfoVo.class, false);
    final AuthenticationManager authenticationManager;
    final PasswordEncoder passwordEncoder;
    final SystemUsersService systemUsersService;
    final SystemUserRoleService systemUserRoleService;
    final SystemDepartmentService systemDepartmentService;
    final SystemRoleMenuService systemRoleMenuService;
    final Department department;

    /**
     * @Description 用户登录
     * @param userLoginInfo
     * @return java.lang.String
     * @Date 2020/11/13 15:08
     * @Author wangyl
     * @Version V1.0
     */
    @Override
    public String login(UserLoginInfo userLoginInfo) {
        /**
         * 验证用户信息
         */
        Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(userLoginInfo.getUsername(), userLoginInfo.getPassword()));
        /**
         * 设置权限信息
         */
        SecurityContextHolder.getContext()
                             .setAuthentication(authentication);
        SecurityUserInfo userDetail = (SecurityUserInfo) authentication.getPrincipal();

        /**
         * 生成token信息
         */
        String userToken = UserInfoJwt.generateUserInfoToken(userDetail.getUsername(), userDetail.getAuthorities(), userDetail.getUserId()
                                                                                                                              .toString());
        return userToken;
    }

    /**
     * @Description 用户退出
     * @return void
     * @Date 2020/11/13 15:08
     * @Author wangyl
     * @Version V1.0
     */
    @Override
    public void logout() {

    }

    /**
     * @Description 添加用户
     * @param userInfoVo
     * @return void
     * @Date 2020/11/13 15:09
     * @Author wangyl
     * @Version V1.0
     */
    @Override
    public void addUser(UserInfoVo userInfoVo) {
        SystemUsers systemUsers = new SystemUsers();
        copier.copy(userInfoVo, systemUsers, null);
        systemUsers.setPassword(passwordEncoder.encode(systemUsers.getPassword()));
        systemUsers.setOperator(UserTools.tools.getUserNameByRequest());
        systemUsersService.save(systemUsers);
    }

    /**
     * @Description 通过id删除用户
     * @param userId
     * @return void
     * @Date 2020/11/13 15:09
     * @Author wangyl
     * @Version V1.0
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteUser(long userId) {
        systemUserRoleService.deleteSystemUserRoleByUserId(userId);
        systemUsersService.removeById(userId);
    }

    /**
     * @Description 更新用户信息
     * @param systemUsers
     * @return void
     * @Date 2020/11/13 15:10
     * @Author wangyl
     * @Version V1.0
     */
    @Override
    public void updateUser(SystemUsers systemUsers) {
        if (!Objects.isNull(systemUsers.getPassword())) {
            systemUsers.setPassword(passwordEncoder.encode(systemUsers.getPassword()));
        }
        systemUsersService.updateById(systemUsers);
    }

    /**
     * @Description 获取当前用户信息
     * @return com.wyl.xue.admin.system.vo.UserInfoVo
     * @Date 2020/11/13 15:11
     * @Author wangyl
     * @Version V1.0
     */
    @Override
    public UserInfoVo getCurrentUserInfo() {
        UserDetails userInfoByRequest = UserTools.tools.getUserInfoByRequest();
        SystemUsers systemUsers = systemUsersService.getSystemUserInfoByUserName(userInfoByRequest.getUsername());
        systemUsers.setUserId(null);
        UserInfoVo userInfoVo = new UserInfoVo();
        copierFrom.copy(systemUsers, userInfoVo, null);
        List<String> collect = userInfoByRequest.getAuthorities()
                                                .parallelStream()
                                                .map(t -> {
                                                    return t.toString();
                                                })
                                                .collect(Collectors.toList());
        userInfoVo.setPermission(collect);
        return userInfoVo;
    }

    /**
     * @Description 通过部门id 后去该部门下的用户信息
     * @param departmentId
     * @return java.util.List<com.wyl.xue.admin.system.mybatis.entity.SystemUsers>
     * @Date 2020/11/13 15:12
     * @Author wangyl
     * @Version V1.0
     */
    @Override
    public Page<SystemUsers> getUserInfoBydepartmentId(long departmentId, int page, int size) {
        List<Object> departmentAllChildNodes = department.getDepartmentAllChildNodes(departmentId);
        departmentAllChildNodes.add(departmentId);
        LambdaQueryWrapper<SystemUsers> systemUsersLambdaQueryWrapper = Wrappers.lambdaQuery(SystemUsers.class)
                                                                                .in(SystemUsers::getDepartmentId, departmentAllChildNodes);
        Page<SystemUsers> userPage = new Page<>(page, size);
        return systemUsersService.page(userPage, systemUsersLambdaQueryWrapper);
    }

    /**
     * @Description 获取当前用户可访问路由
     * @return java.util.Set<java.lang.Long>
     * @Date 2020/11/13 15:14
     * @Author wangyl
     * @Version V1.0
     */
    @Override
    public Set<Long> getCurrentUserAccessRouter() {
        SecurityUserInfo systemUsers = (SecurityUserInfo) UserTools.tools.getUserInfoByRequest();
        List<Long> rolesId = systemUserRoleService.getSystemUserRoleByUserId(systemUsers.getUserId());
        Set<Long> menusByRoleIds = systemRoleMenuService.getMenusByRoleIds(rolesId);
        return menusByRoleIds;
    }

    /**
     * @Description 设置用户的角色
     * @param userId
     * @param roleIds
     * @return void
     * @Date 2020/11/13 15:15
     * @Author wangyl
     * @Version V1.0
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void setUserRoles(long userId, List<Long> roleIds) {
        systemUserRoleService.deleteSystemUserRoleByUserId(userId);
        List<SystemUserRole> userRoleBuilders = roleIds.parallelStream()
                                                       .map(roleId -> SystemUserRole.builder()
                                                                                    .roleId(roleId)
                                                                                    .UserId(userId)
                                                                                    .build())
                                                       .collect(Collectors.toList());
        systemUserRoleService.saveBatch(userRoleBuilders);
    }

    /**
     * @Description 通过用户名获取用户信息
     * @param name
     * @return com.wyl.xue.admin.system.mybatis.entity.SystemUsers
     * @Date 2020/11/16 23:26
     * @Author wangyl
     * @Version V1.0
     */
    @Override
    public SystemUsers getSystemUsersByName(String name) {
        return systemUsersService.getSystemUserInfoByUserName(name);
    }

    /**
     * @Description 通过用户id获取用户权限
     * @param userId
     * @return java.util.List<java.lang.String>
     * @Date 2020/11/16 23:27
     * @Author wangyl
     * @Version V1.0
     */
    @Override
    public Set<String> getSystemPermissionsByUserId(long userId) {
        List<Long> rolesId = systemUserRoleService.getSystemUserRoleByUserId(userId);
        Set<String> menusByRoleIds = systemRoleMenuService.getPermByRoleIds(rolesId);
        return menusByRoleIds;
    }

    /**
     * @Description 搜索用户
     * @param userInfoVo
     * @return java.util.List<com.wyl.xue.admin.system.mybatis.entity.SystemDepartment>
     * @Date 2020/11/21 22:30
     * @Author wangyl
     * @Version V1.0
     */
    @Override
    public List<SystemUsers> searchUser(UserInfoVo userInfoVo) {
        LambdaQueryWrapper<SystemUsers> usersLambdaQueryWrapper = Wrappers.lambdaQuery(SystemUsers.class)
                                                                          .like(!Objects.isNull(userInfoVo.getUsername()), SystemUsers::getUsername, userInfoVo.getUsername())
                                                                          .like(!Objects.isNull(userInfoVo.getPhoneNumber()), SystemUsers::getPhoneNumber, userInfoVo.getPhoneNumber())
                                                                          .like(!Objects.isNull(userInfoVo.getEmail()), SystemUsers::getEmail, userInfoVo.getEmail());
        return systemUsersService.list(usersLambdaQueryWrapper);
    }
}
